package com.n11.imic.cache;
import com.n11.imic.config.ImageScalerConfigFileLocator;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.DiskStoreConfiguration;
import net.sf.ehcache.config.PersistenceConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import org.apache.commons.configuration.XMLConfiguration;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class CacheManager {
private Cache imageCache;
private net.sf.ehcache.CacheManager cacheManager = null;
private final ReadWriteLock cacheLock = new ReentrantReadWriteLock();
private CacheManager() {
}
public void initConfiguration() {
try {
shutdownCacheIfNeeded();
XMLConfiguration xmlConfiguration = new XMLConfiguration(ImageScalerConfigFileLocator.findConfigFile());
if (xmlConfiguration.getKeys("cache").hasNext()) {
CacheConfiguration cacheConfiguration = initCacheConfiguration(xmlConfiguration);
initCacheManager(cacheConfiguration, xmlConfiguration.getString("cache[@diskStorePath]", ""));
}
} catch (Exception ce) {
cacheLock.writeLock().unlock();
throw new IllegalArgumentException("Cannot instantiate cache, problem with the configuration", ce);
}
}
private CacheConfiguration initCacheConfiguration(XMLConfiguration xmlConfiguration) {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setName("ImageCache");
cacheConfiguration.setEternal(xmlConfiguration.getBoolean("cache[@eternal]", false));
cacheConfiguration.setMaxEntriesLocalHeap(xmlConfiguration.getLong("cache[@maxEntriesLocalHeap]", CacheConfiguration.DEFAULT_MAX_ENTRIES_IN_CACHE));
cacheConfiguration.setMaxEntriesInCache(xmlConfiguration.getLong("cache[@maxEntriesInCache]", CacheConfiguration.DEFAULT_MAX_ENTRIES_IN_CACHE));
cacheConfiguration.setMaxBytesLocalDisk(xmlConfiguration.getString("cache[@maxBytesLocalDisk]", "10g"));
cacheConfiguration.setMaxBytesLocalHeap(xmlConfiguration.getString("cache[@maxBytesLocalHeap]", "1g"));
cacheConfiguration.setMaxBytesLocalOffHeap(xmlConfiguration.getString("cache[@maxBytesLocalOffHeap]", "1000000"));
cacheConfiguration.setOverflowToOffHeap(xmlConfiguration.getBoolean("cache[@overflowToOffHeap]", false));
return cacheConfiguration;
}
private void initCacheManager(CacheConfiguration cacheConfiguration, String diskStorePath) {
DiskStoreConfiguration dsc = new DiskStoreConfiguration();
dsc.setPath(diskStorePath);
Configuration cacheConfig = new Configuration();
cacheConfig.addDiskStore(dsc);
cacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU);
cacheConfiguration.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP));
cacheManager = new net.sf.ehcache.CacheManager(cacheConfig);
lockWriteCache();
imageCache = new Cache(cacheConfiguration);
cacheManager.addCache(imageCache);
cacheConfig.setDefaultCacheConfiguration(cacheConfiguration);
unlockWriteCache();
}
private void shutdownCacheIfNeeded() {
if (imageCache != null ) {
cacheManager.removeAllCaches();
cacheManager.shutdown();
}
}
public boolean isCacheEnabled() {
return getImageCache() != null;
}
public Cache getImageCache() {
return imageCache;
}
public void lockWriteCache() {
cacheLock.writeLock().lock();
}
public void unlockWriteCache() {
cacheLock.writeLock().unlock();
}
public Element getImageFromCache(String pathInfo) {
return imageCache.get(pathInfo);
}
public void shutdownCacheManager() {
cacheManager.shutdown();
}
public void putToCacheIfCacheExists(String path, byte[] data, Map<String, String> responseHeaders) {
if (isCacheEnabled()) {
lockWriteCache();
try {
imageCache.put(new net.sf.ehcache.Element(path, new CachedImage(data, responseHeaders)));
} finally {
unlockWriteCache();
}
}
}
public void lockReadCache() {
cacheLock.readLock().lock();
}
public void unlockReadCache() {
cacheLock.readLock().unlock();
}
private static class CacheManagerHolder {
public final static CacheManager instance = new CacheManager();
private CacheManagerHolder(){
}
}
public static CacheManager getInstance() {
return CacheManagerHolder.instance;
}
}